package com.gitee.huxing.framework.redis;

import com.gitee.huxing.framework.utils.ApplicationContextHelper;
import com.gitee.huxing.framework.utils.ThreadTaskHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisOperations;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description: 自定义redis缓存
 * @ProjectName: SpringCloudLearning
 * @Package: com.huxing.framework.redis
 * @ClassName: CustomizedRedisCache
 * @Author: huxing
 * Date: 2021-05-24
 * Time: 10:46
 */
@Slf4j
@SuppressWarnings("all")
public class CustomizedRedisCache extends RedisCache {

    private RedisOperations redisOperations;

    private static final Lock REFRESH_CACKE_LOCK = new ReentrantLock();

    private CacheSupport getCacheSupport(){
        return ApplicationContextHelper.getApplicationContext().getBean(CacheSupport.class);
    }


    public CustomizedRedisCache(String name, RedisCacheWriter cacheWriter, RedisCacheConfiguration cacheConfig, RedisOperations redisOperations) {
        super(name, cacheWriter, cacheConfig);
        this.redisOperations=redisOperations;
    }

    public Cache.ValueWrapper get(final Object key) {
        Cache.ValueWrapper valueWrapper= super.get(key);
        if(null!=valueWrapper){
            CacheItemConfig cacheItemConfig = CacheContainer.getCacheItemConfigByCacheName(key.toString());
            long preLoadTimeSecond = cacheItemConfig.getPreLoadTimeSecond();
            String cacheKey = this.createCacheKey(key);
            Long ttl= this.redisOperations.getExpire(cacheKey);
            if(null!=ttl && ttl<=preLoadTimeSecond){
                log.info("key:{}  ttl:{}  preloadSecondTime:{}", cacheKey, ttl, preLoadTimeSecond);
                if(ThreadTaskHelper.hasRunningRefreshCacheTask(cacheKey)){
                    log.info("do not need to refresh");
                } else {
                    ThreadTaskHelper.run(() -> {
                        try {
                            REFRESH_CACKE_LOCK.lock();
                            if(ThreadTaskHelper.hasRunningRefreshCacheTask(cacheKey)){
                                log.info("do not need to refresh");
                            }
                            else {
                                // 刷新缓存记录信息
                                log.info("refresh key:{}", cacheKey);
                                CustomizedRedisCache.this.getCacheSupport().
                                        refreshCacheByKey(CustomizedRedisCache.super.getName(), key.toString());
                                ThreadTaskHelper.removeRefreshCacheTask(cacheKey);
                            }
                        }
                        finally
                        {
                            REFRESH_CACKE_LOCK.unlock();
                        }
                    });
                }
            }
        }
        return valueWrapper;
    }
}
